#include "parser.h"

#include "error.h"


void Parser::process(const std::wstring &code) {
  tokens.clear();
  pos = 0;

  lexer.set_code(code);
  while (true) {
    Token token = lexer.next();
    if (token.kind == SPACE)continue; // TODO 暂时忽略空格
    tokens.push_back(token);
    if (token.kind == EOL)break;
  }

  file();
}

/**
 * file := {stmt}
 * */
void Parser::file() {
  while (pos < tokens.size())stmt();
}

/**
 * stmt := expr ( CR | EOL )
 * */
void Parser::stmt() {
  expr();
  if (tokens[pos].kind == CR || tokens[pos].kind == EOL) pos++;
  else throw SyntaxError("语法错误", pos);
}

/**
 * expr := call_expr
 * */
void Parser::expr() {
  call_expr();
}

/**
 * call_expr := dot_expr '(' expr { ',' expr } ')'
 *            | dot_expr '(' ')'
 *            | dot_expr
 * */
void Parser::call_expr() {
  dot_expr();

  if (tokens[pos].kind == OP && tokens[pos].text == L"(") {
    pos++;

    if (tokens[pos].kind != OP || tokens[pos].text != L")") {
      expr();

      while (tokens[pos].kind == OP && tokens[pos].text == L",") {
        pos++;
        expr();
      }
    }

    if (tokens[pos].kind != OP || tokens[pos].text == L")") {
      throw SyntaxError("语法错误", pos);
    }

    pos++;
  }
}

/**
 * dot_expr := primary_expr { '.' ID }
 * */
void Parser::dot_expr() {
  primary_expr();
  while (tokens[pos].kind == OP && tokens[pos].text == L".") {
    pos++;
    if (tokens[pos].kind == ID) {
      pos++;
    } else throw SyntaxError("语法错误", pos);
  }
}

/**
 * primary_expr := '(' expr ')'
 *               | call_expr
 *               | LITERAL
 *               | ID
 * */
void Parser::primary_expr() {
  if (tokens[pos].kind == OP && tokens[pos].text == L"(") {
    expr();
    if (tokens[pos].kind != OP || tokens[pos].text == L")")throw SyntaxError("语法错误", pos);
    pos++;
    return;
  }

  if (tokens[pos].kind == LITERAL) {
    pos++;
    return;
  }

  if (tokens[pos].kind == ID) {
    pos++;
    return;
  }

  call_expr();
}
